package com.xueyl.springboot.aspect;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.mongodb.BasicDBObject;
import com.mongodb.connection.Stream;

@Aspect
@Component
public class WebLogAspect {
	ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	private Logger log = Logger.getLogger("mongodb");

	@Pointcut("execution(public * com.xueyl.springboot.web..*.*(..))")
	public void webLog(){}
	
	@Before(value="webLog()")
	public void doBefore(JoinPoint joinPoint){
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
		BasicDBObject logInfo = getBasicDBObject(request, joinPoint);
		log.info(logInfo);
		
	}
	private BasicDBObject getBasicDBObject(HttpServletRequest request, JoinPoint joinPoint) {
		BasicDBObject dbObject = new BasicDBObject();
		dbObject.append("requestURL", request.getRequestURL().toString());
		dbObject.append("requestURI", request.getRequestURI());
		dbObject.append("queryString", request.getQueryString());
		dbObject.append("remoteAddr", request.getRemoteAddr());
		dbObject.append("remoteHost", request.getRemoteHost());
		dbObject.append("remotePort", request.getRemotePort());
        dbObject.append("localAddr", request.getLocalAddr());
        dbObject.append("localName", request.getLocalName());
        dbObject.append("method", request.getMethod());
        dbObject.append("headers", getHeadersInfo(request));
        dbObject.append("parameters", request.getParameterMap());
        dbObject.append("classMethod", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        dbObject.append("args", Arrays.toString(joinPoint.getArgs()));
	   return dbObject;
	}

	private Map<String,String> getHeadersInfo(HttpServletRequest request) {
		Map<String,String> headers = new HashMap<>();
		Enumeration<String> headerNames = request.getHeaderNames();
		
		while(headerNames.hasMoreElements()){
			String key = headerNames.nextElement();
			String value = request.getHeader(key);
			headers.put(key, value);
		}
		return headers;
	}

	@AfterReturning(value = "webLog()")
	public void doAfter(){
	}
	
}
